/*
 *@file		dhdm.cpp
 *
 *@brief	DH device manage. 
 *
 *@author	liangbing
 *@date		2012-05-14
 *@version	1.0
 *$Id: dhdm.cpp,v 1.0 2012/05/14 13:27:01 liangbing Exp $
 */


#include "dhdm.h"




//---------------------------The variable definition--------------------------------------
DEVICE_LIST 	g_DeviceList;




//---------------------------The function prototype---------------------------------------
BOOL ReceiveMessage(DH_Device_Info * p, LONG lLoginID, LONG lCommand, 
		char *pchDVRIP, LONG nDVRPort, char *pBuf, DWORD dwBufLen);

BOOL ReceiveMessageEx(DH_Device_Info * p, LONG lLoginID, LONG lCommand, 
		char *pchDVRIP, LONG nDVRPort, char *pBuf, DWORD dwBufLen);

void DHCommAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHInputAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHMotionDetectAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHVideoLostAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHShelterAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHDiskFullAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHDiskFullAlarmEx(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHDiskErrorAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHDiskErrorAlarmEx(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);
void DHSoundAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen);




//---------------------------The function definition--------------------------------------
void CALLBACK DisConnectFunc(LONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser) 
{ 
	printf( "disconnect loginID=%ld, ip=%s, port=%ld\n", lLoginID, pchDVRIP, nDVRPort );

    DEVICE_LIST::iterator it = g_DeviceList.begin();
	for (;it != g_DeviceList.end(); it++) {
		DH_Device_Info * pDeviceInfo = (*it);
		if (pDeviceInfo != NULL && pDeviceInfo->lLoginHandle == lLoginID) {
			pDeviceInfo->bOnline = FALSE;
#ifdef DF_CHANNEL
			for(int i = 0; i < pDeviceInfo->nChannelCount; i++) {
				pDeviceInfo->channel[i].dwStatistic = 0;
			}
#endif
			break;
		}
	}
}


void CALLBACK HaveReConnect( LONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser)
{
	printf( "reconnect loginID=%ld, ip=%s, port=%ld\n", lLoginID, pchDVRIP, nDVRPort );

	DEVICE_LIST::iterator it = g_DeviceList.begin();
	for (;it != g_DeviceList.end(); it++) {
		DH_Device_Info * pDeviceInfo = (*it);
		if (pDeviceInfo != NULL && pDeviceInfo->lLoginHandle == lLoginID) {
			pDeviceInfo->bOnline = TRUE;
			break;
		}
	}
}


#ifdef DF_CHANNEL
void CALLBACK RealDataCallBack(LONG lRealHandle, DWORD dwDataType, 
		BYTE * pBuffer, DWORD dwBufSize, DWORD dwUser) 
{ 
	printf( "dwDataType=%ld, dwBufSize=%ld\n", dwDataType, dwBufSize );
	DH_Channel_Info* pChannelInfo = (DH_Channel_Info*)dwUser; 
	if(NULL == pChannelInfo) { 
		return; 
	}

	pChannelInfo->dwStatistic += dwBufSize; 
}
#endif


BOOL CALLBACK MessageCallBack(LONG lCommand, LONG lLoginID, char *pBuf, DWORD dwBufLen, 
		char *pchDVRIP, LONG nDVRPort, DWORD dwUser)
{
	DEVICE_LIST::iterator it = g_DeviceList.begin();
	for (;it != g_DeviceList.end(); it++) {
		DH_Device_Info * p = *it;
		if (p == NULL || p->lLoginHandle != lLoginID) {
			continue;
		}
		if (p->protocalVersion < 5) {
			return ReceiveMessage(p, lLoginID, lCommand, pchDVRIP, nDVRPort, pBuf, dwBufLen);
		} else {
			return ReceiveMessageEx(p, lLoginID, lCommand, pchDVRIP, nDVRPort, pBuf, dwBufLen);
		}
	}
	return FALSE;
}


int InitDeviceInfo(const char * ip, int port, const char * username, const char * password)
{
	DH_Device_Info * device_info = new DH_Device_Info;
	if (NULL == device_info) { 
		printf( "ERR: NULL == device_info \n" );
		return 0;
	} 
	memset(device_info, 0, sizeof(DH_Device_Info)); 

	strncpy(device_info->szDevIp, ip, sizeof(device_info->szDevIp) - 1); 
	device_info->nPort = port; 
	strncpy(device_info->szUserName, username, sizeof(device_info->szUserName) - 1);
	strncpy(device_info->szPassWord, password, sizeof(device_info->szPassWord) - 1); 

	g_DeviceList.push_back(device_info); 
    return 1;
}


int InitDMEnv()
{
	InitDeviceInfo("192.168.1.107", 37777, "admin", "admin");
	InitDeviceInfo("192.168.1.113", 37777, "admin", "admin");
	InitDeviceInfo("219.130.136.229", 37777, "JMWJ", "779218");
	InitDeviceInfo("61.145.9.125", 37777, "JMWJ", "081110");

    if( !CLIENT_Init(DisConnectFunc, (DWORD)NULL) ) {
		return 0;
	}

	CLIENT_SetAutoReconnect( HaveReConnect, (DWORD)NULL );
	CLIENT_SetDVRMessCallBack( MessageCallBack, (DWORD)NULL );
	return 1;
}


void DestroyDMEnv( )
{
    CLIENT_Cleanup(); 
}


void StartDevices( )
{
	int error = 0;
    NET_DEVICEINFO deviceInfo; 
    DEVICE_LIST::iterator it = g_DeviceList.begin();
    for (;it != g_DeviceList.end(); it++) {
        DH_Device_Info * pDeviceInfo = (*it);
        if (pDeviceInfo == NULL) {
            continue;
		}

		pDeviceInfo->lLoginHandle = CLIENT_Login(pDeviceInfo->szDevIp, pDeviceInfo->nPort,
				pDeviceInfo->szUserName, pDeviceInfo->szPassWord, &deviceInfo, &error);
		if (pDeviceInfo->lLoginHandle == 0) {
			printf( "login failed,error = %d\n", error);
			pDeviceInfo->bOnline = FALSE;
			continue;
		}

		printf( "SerialNum=%s, AlarmInPortNum=%d, AlarmOutPortNum=%d, DiskNum=%d, DVRType=%d, ChannelNum=%d\n", 
				deviceInfo.sSerialNumber, deviceInfo.byAlarmInPortNum,
				deviceInfo.byAlarmOutPortNum, deviceInfo.byDiskNum, 
				deviceInfo.byDVRType, deviceInfo.byChanNum );

		pDeviceInfo->bOnline = TRUE;
#ifdef DF_CHANNEL
		pDeviceInfo->nChannelCount = deviceInfo.byChanNum;
		int nLoopCount = pDeviceInfo->nChannelCount;
		if (nLoopCount > 16) {
			nLoopCount = 16;
		}

		for (int i = 0; i < nLoopCount; i++) {
			pDeviceInfo->channel[i].lRealPlayHandle = CLIENT_RealPlay(
					pDeviceInfo->lLoginHandle, i, NULL);
			if (pDeviceInfo->channel[i].lRealPlayHandle != 0) {
				CLIENT_SetRealDataCallBack( pDeviceInfo->channel[i].lRealPlayHandle, 
						RealDataCallBack, (DWORD)&(pDeviceInfo->channel[i]));
			} else {
				printf("loginid = %ld;real play failed!\n", pDeviceInfo->lLoginHandle);
			}
		}
#endif

		int nRetLen = 0;
		BOOL bSuccess = CLIENT_QueryDevState( pDeviceInfo->lLoginHandle, 
				DH_DEVSTATE_PROTOCAL_VER, (char*)&pDeviceInfo->protocalVersion,
				sizeof(int), &nRetLen, 1000);
		if (!bSuccess) {
			printf( "WARN: device state query fail!\n" );
		}

		BOOL bRet = FALSE;
		if (pDeviceInfo->protocalVersion < 5) {
			bRet = CLIENT_StartListen( pDeviceInfo->lLoginHandle );
		} else  {
			bRet = CLIENT_StartListenEx( pDeviceInfo->lLoginHandle );
		}
		if (!bRet) {
			printf( "WARN: start listen fail!\n" );
		}
	}
}

    
void StopDevices()
{
    DEVICE_LIST::iterator it = g_DeviceList.begin();
	for (; it != g_DeviceList.end(); it++) {
		DH_Device_Info * pDeviceInfo = *it;
		if (pDeviceInfo->lLoginHandle > 0) {	 
#ifdef DF_CHANNEL
			int nCount = pDeviceInfo->nChannelCount;
			if (nCount > 16) {
				nCount = 16;
			}
			for (int i = 0; i < nCount; i++) { 
				CLIENT_StopRealPlay(pDeviceInfo->channel[i].lRealPlayHandle); 
			} 
#endif

			CLIENT_StopListen(pDeviceInfo->lLoginHandle);
			CLIENT_Logout(pDeviceInfo->lLoginHandle); 
		} 

		delete pDeviceInfo;
	}

	g_DeviceList.clear();
}


BOOL ReceiveMessage(DH_Device_Info * p, LONG lLoginID, LONG lCommand, 
		char *pchDVRIP, LONG nDVRPort, char *pBuf, DWORD dwBufLen)
{
	BOOL bRet = TRUE;
	switch(lCommand) {
		case DH_COMM_ALARM:		
			DHCommAlarm(p, pBuf,dwBufLen);
			break;
		case DH_SHELTER_ALARM:		
			DHShelterAlarm(p, pBuf,dwBufLen);
			break;
		case DH_DISK_FULL_ALARM:	
			DHDiskFullAlarm(p, pBuf,dwBufLen);
			break;
		case DH_DISK_ERROR_ALARM:	
			DHDiskErrorAlarm(p, pBuf,dwBufLen);	
			break;
		case DH_SOUND_DETECT_ALARM:		
			DHSoundAlarm(p, pBuf,dwBufLen);	
			break;
		case DH_ALARM_DECODER_ALARM:	
			break;
		default:
			bRet = FALSE;
			break;
	}

	return bRet;
}


BOOL ReceiveMessageEx(DH_Device_Info * p, LONG lLoginID, LONG lCommand, 
		char *pchDVRIP, LONG nDVRPort, char *pBuf, DWORD dwBufLen)
{
    BOOL bRet = TRUE;
	switch(lCommand) {
		case DH_ALARM_ALARM_EX:	
			DHInputAlarm(p, pBuf, dwBufLen);
			break;
		case DH_MOTION_ALARM_EX:		
			DHMotionDetectAlarm(p, pBuf, dwBufLen);
			break;
		case DH_VIDEOLOST_ALARM_EX:		
			DHVideoLostAlarm(p, pBuf, dwBufLen);
			break;
		case DH_SHELTER_ALARM_EX:		
			DHShelterAlarm(p, pBuf, dwBufLen);
			break;
		case DH_SOUND_DETECT_ALARM_EX:	
			DHSoundAlarm(p, pBuf, dwBufLen);	
			break;
		case DH_DISKFULL_ALARM_EX:		
			DHDiskFullAlarmEx(p, pBuf, dwBufLen);
			break;
		case DH_DISKERROR_ALARM_EX:		
			DHDiskErrorAlarmEx(p, pBuf, dwBufLen);
			break;
		case DH_ENCODER_ALARM_EX:		
			break;
		case DH_URGENCY_ALARM_EX:		
			break;
		case DH_WIRELESS_ALARM_EX:		
			break;
		default:
			bRet = FALSE;
			break;
	}

	return bRet;
}


void DHCommAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    NET_CLIENT_STATE *pState = (NET_CLIENT_STATE *)pBuf;
    if (dwBufLen != sizeof(NET_CLIENT_STATE) || pState == NULL) {
        return;
    }
	
	p->alarm.alarmType = DH_COMMON_ALARM;
    p->alarm.channelCount = pState->channelcount;
    p->alarm.alarmInputCount = pState->alarminputcount;

    int i = 0;
    for( i = 0; i < p->alarm.alarmInputCount; i++) {
        if (1 == pState->alarm[i]) {
            p->alarm.inputAlarm = p->alarm.inputAlarm | (1<<i);
        }	
    }

    for( i = 0; i < p->alarm.channelCount; i++) {
        if (1 == pState->videolost[i]) {
            p->alarm.videoLost = p->alarm.videoLost | (1<<i);
        }     
    }
  
    for( i = 0; i < p->alarm.channelCount; i++) {
        if (1 == pState->motiondection[i]) {
            p->alarm.motionDetect = p->alarm.motionDetect | (1<<i);
        }		
    }
}


void DHInputAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != 16) {
        return;
    }

	p->alarm.alarmType = DH_INPUT_ALARM;
    for( int i = 0; i < 16; i++) {
        if (1 == pBuf[i]) {
            p->alarm.inputAlarm = p->alarm.inputAlarm | (1<<i);
        }	
    }
}


void DHMotionDetectAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != 16) {
        return;
    }

	p->alarm.alarmType = DH_MOTIONDETECT_ALARM;
    for( int i = 0; i < 16; i++) {
        if (1 == pBuf[i]) {
            p->alarm.motionDetect = p->alarm.motionDetect | (1<<i);
        }	
    }
}


void DHVideoLostAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != 16) {
        return;
    }

	p->alarm.alarmType = DH_VIDEOLOST_ALARM;
    for( int i = 0; i < 16; i++) {
        if (1 == pBuf[i]) {
            p->alarm.videoLost = p->alarm.videoLost | (1<<i);
        }	
    }
}


void DHShelterAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
	if (dwBufLen != 16) {
		return;
	}

	p->alarm.alarmType = DH_VIDEOSHELTER_ALARM;

	for (int i=0; i<16; i++) {
		if (1 == pBuf[i]) {
			p->alarm.shelterAlarm = p->alarm.shelterAlarm | (1<<i);	
		}
	}
}


void DHDiskFullAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != sizeof(DWORD)) {
        return;
    }

	p->alarm.alarmType = DH_DISKFULL_ALARM;

    DWORD dwDiskFull = *(DWORD*)pBuf;
    if (1 == dwDiskFull) {
        p->alarm.diskFull = TRUE;
    }
}


void DHDiskFullAlarmEx(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != 1) {
        return;
    }

	p->alarm.alarmType = DH_DISKFULL_ALARM;
	if (1 == pBuf[0]) {
		p->alarm.diskFull = TRUE;
	}
}


void DHDiskErrorAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != sizeof(DWORD)) {
        return;
    }

	p->alarm.alarmType = DH_DISKERROR_ALARM;
    p->alarm.diskError = *(DWORD*)pBuf;
}


void DHDiskErrorAlarmEx(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != 32) {
        return;
    }

	p->alarm.alarmType = DH_DISKERROR_ALARM;
    for( int i=0; i<32; i++) {
        if (1 == pBuf[i]) {
            p->alarm.diskError = p->alarm.diskError | (1<<i);
        }
    }
}


void DHSoundAlarm(DH_Device_Info * p, char *pBuf, DWORD dwBufLen)
{
    if (dwBufLen != 16) {
        return;
    }

	p->alarm.alarmType = DH_SOUNDDETECT_ALARM;
    for( int i=0; i<16; i++) {
        if (1 == pBuf[i]) {
            p->alarm.soundDetect = p->alarm.soundDetect | (1<<i);
        }
    }
}


